---
title: Weights and Fees
slug: /v3/runtime/weights-and-fees
version: '3.0'
section: docs
category: runtime
keywords:
---

Because the resources available to a blockchain are limited, it’s important to manage how blocks consume them.
The resources that need to be managed include:

- Memory usage
- Storage input and output
- Computation
- Transaction and block size
- State database size

Substrate provides block authors with several ways to manage access to resources and to prevent individual components of the chain from consuming too much of any single resource.
Two of the most important mechanisms available to block authors are **weights** and **transaction fees**.

[Weights](/v3/concepts/weight) are used to manage the time it takes to validate a block.
In general, weights are used to characterize the time it takes to execute the [extrinsic](/v3/concepts/extrinsics) calls in the body of a block.
By controlling the execution time that a block can consume, weights set limits on storage input and output and computation.

<Message
  type={`gray`}
  title={`Note`}
  text={`Weights are not used to restrict access to other resources, such as storage itself or memory footprint. Other mechanisms must be used for this.`}
/>

Some of the weight allowed for a block is consumed as part of the block's initialization and finalization.
The weight might also be used to execute mandatory inherent extrinsic calls.
To help ensure blocks don’t consume too much execution time—and prevent malicious users from overloading the system with unnecessary calls—weights are used in combination with transaction fees.

Transaction fees are a key component of making the blockchain economically sustainable and are typically applied to transactions initiated by users and deducted before a transaction request is executed.

## How fees are calculated

The final fee for a transaction is calculated using the following parameters:

- _base fee_: This is the minimum amount a user pays for a transaction. It is declared as a **base weight** in the runtime and converted to a fee using `WeightToFee`.

- _weight fee_: A fee proportional to the execution time (input and output and computation) that a transaction consumes.

- _length fee_: A fee proportional to the encoded length of the transaction.

- _tip_: An optional tip to increase the priority of the transaction, giving it a higher chance to be included by the transaction queue.

The base fee and proportional weight and length fees constitute the **inclusion fee**.
The inclusion fee is the minimum fee that must be available for a transaction to be included in a block.

## Using the transaction payment pallet

The [Transaction Payment pallet](/rustdocs/latest/pallet_transaction_payment/index.html) provides the basic logic for calculating the inclusion fee.

You can also use the Transaction Payment pallet to:

- Convert a weight value into a deductible fee based on a currency type using `Config::WeightToFee`.

- Update the fee for the next block by defining a multiplier, based on the final state of the chain at the end of the previous block using `Config::FeeMultiplierUpdate`.

- Manage the withdrawal, refund, and deposit of transaction fees using `Config::OnChargeTransaction`.

You can learn more about these configuration traits in the [Transaction Payment](/rustdocs/latest/pallet_transaction_payment/index.html) documentation.

You should note that transaction fees are withdrawn before the transaction is executed.
After the transaction is executed, the transaction weight can be adjusted to reflect the actual resources the transaction used.
If a transaction uses fewer resources than expected, the transaction fee is corrected and the adjusted transaction fee is deposited.

### A closer look at the inclusion fee

The formula for calculating the final fee looks like this:

```
inclusion_fee = base_fee + length_fee + [targeted_fee_adjustment * weight_fee];
final_fee = inclusion_fee + tip;
```

In this formula, the `targeted_fee_adjustment` is a multiplier that can tune the final fee based on the congestion of the network.

- The `base_fee` derived from the base weight covers inclusion overhead like signature verification.

- The `length_fee` is a per-byte fee that is multiplied by the length of the encoded extrinsic.

- The `weight_fee` fee is calculated using two parameters:

  The `ExtrinsicBaseWeight` that is declared in the runtime and applies to all extrinsics.

  The `#[pallet::weight]` annotation that accounts for an extrinsic's complexity.

To convert the weight to Currency, the runtime must define a `WeightToFee` struct that implements a conversion function, `Convert<Weight,Balance>`.

Note that the extrinsic sender is charged the inclusion
fee before the extrinsic is invoked. The fee is deducted from the sender's balance even if the transaction fails upon execution.

### Accounts with an insufficient balance

If an account does not have a sufficient balance to pay the inclusion fee and remain alive—that is, enough to pay the inclusion fee and maintain the minimum **existential deposit**—then you should ensure the transaction is cancelled so that no fee is deducted and the transaction does not begin execution.

Substrate does not enforce this rollback behavior.
However, this scenario would be a rare occurrence because the transaction queue and block-making logic perform checks to prevent it before adding an extrinsic to a block.

### Fee multiplier

The inclusion fee formula always results in the same fee for the same input.
However, weight can be dynamic and—based on how
[`WeightToFee`](/rustdocs/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.WeightToFee)
is defined—the final fee can include some degree of variability.

To account for this variability, the Transaction Payment pallet provides the [`FeeMultiplierUpdate`](/rustdocs/latest/pallet_transaction_payment/pallet/trait.Config.html#associatedtype.FeeMultiplierUpdate) configurable parameter.

The default update function is inspired by the Polkadot network and implements a targeted adjustment in which a target saturation level of block weight is defined.
If the previous block is more saturated, then the fees are slightly increased.
Similarly, if the previous block has fewer transactions than the target, fees are decreased by a small amount.
For more information about fee multiplier adjustments, see the
[Web3 research page](https://w3f-research.readthedocs.io/en/latest/polkadot/overview/2-token-economics.html#relay-chain-transaction-fees-and-per-block-transaction-limits).

## Transactions with special requirements

Inclusion fees must be computable prior to execution, and therefore can only represent fixed logic.
Some transactions warrant limiting resources with other strategies.
For example:

- Bonds are a type of fee that might be returned or slashed after some on-chain event.

  For example, you might want to require users to place a bond to participate in a vote. The bond might then be returned at the end of the referendum or slashed if the voter attempted malicious behavior.

- Deposits are fees that might be returned later.

  For example, you might require users to pay a deposit to execute an operation that uses storage. If a subsequent operation frees up storage, the user's deposit could be returned.

* Burn operations are used to pay for a transaction based on its internal logic.

  For example, a transaction might burn funds from the sender if the transaction creates new storage items to pay for the increased the state size.

- Limits enable you to enforce constant or configurable limits on certain operations.

  For example, the default Staking pallet only allows nominators to nominate 16 validators to limit the complexity of the validator election process.

It is important to note that if you query the chain for a transaction fee, it only returns the inclusion fee.

## Default weight annotations

All dispatchable functions in Substrate must specify a weight. The way of doing that is using the
annotation-based system that lets you combine fixed values for database read/write weight and/or
fixed values based on benchmarks. The most basic example would look like this:

```rust
#[pallet::weight(100_000)]
fn my_dispatchable() {
    // ...
}
```

Please note that the `ExtrinsicBaseWeight` is automatically added to the declared weight in order to
account for the costs of simply including an empty extrinsic into a block.

### Parameterizing over database accesses

In order to make weight annotations independent of the deployed database backend, they are defined
as a constant and then used in the annotations when expressing database accesses performed by the
dispatchable:

```rust
#[pallet::weight(T::DbWeight::get().reads_writes(1, 2) + 20_000)]
fn my_dispatchable() {
    // ...
}
```

This dispatchable does one database read and two database writes in addition to other things that
add the additional 20,000. A database access is generally every time a value that is declared inside
the `#[pallet::storage]` block is accessed. However, only unique accesses are counted because once a
value is accessed it is cached and accessing it again does not result in a database operation. That
is:

- Multiple reads of the same value count as one read.
- Multiple writes of the same value count as one write.
- Multiple reads of the same value, followed by a write to that value, count as one read and one
  write.
- A write followed by a read only counts as one write.

### Dispatch classes

Dispatches are broken into three classes: `Normal`, `Operational`, and `Mandatory`. When not defined
otherwise in the weight annotation, a dispatch is `Normal`. The developer can specify that the
dispatchable uses another class like this:

```rust
#[pallet::weight(100_000, DispatchClass::Operational)]
fn my_dispatchable() {
    // ...
}
```

This tuple notation also allows specifying a final argument that determines whether or not the user
is charged based on the annotated weight. When not defined otherwise, `Pays::Yes` is assumed:

```rust
#[pallet::weight(100_000, DispatchClass::Normal, Pays::No)]
fn my_dispatchable() {
    // ...
}
```

#### Normal dispatches

Dispatches in this class represent normal user-triggered transactions. These types of dispatches may
only consume a portion of a block's total weight limit; this portion can be found by examining the
[`AvailableBlockRatio`](/rustdocs/latest/frame_system/limits/struct.BlockLength.html#method.max_with_normal_ratio).
Normal dispatches are sent to the [transaction pool](/v3/concepts/tx-pool).

#### Operational dispatches

As opposed to normal dispatches, which represent _usage_ of network capabilities, operational
dispatches are those that _provide_ network capabilities. These types of dispatches may consume the
entire weight limit of a block, which is to say that they are not bound by the
[`AvailableBlockRatio`](/rustdocs/latest/frame_system/limits/struct.BlockLength.html#method.max_with_normal_ratio).
Dispatches in this class are given maximum priority and are exempt from paying the `length_fee`.

#### Mandatory dispatches

Mandatory dispatches will be included in a block even if they cause the block to surpass its weight
limit. This dispatch class may only be applied to
[inherents](/v3/concepts/extrinsics#inherents) and is intended to represent functions that are
part of the block validation process. Since these kinds of dispatches are always included in a block
regardless of the function weight, it is critical that the function's validation process prevents
malicious validators from abusing the function in order to craft blocks that are valid but
impossibly heavy. This can typically be accomplished by ensuring that the operation is always very
light and can only be included in a block once. In order to make it more difficult for malicious
validators to abuse these types of dispatches, they may not be included in blocks that return
errors. This dispatch class exists to serve the assumption that it is better to allow an overweight
block to be created than to not allow any block to be created at all.

### Dynamic weights

In addition to purely fixed weights and constants, the weight calculation can consider the input
arguments of a dispatchable. The weight should be trivially computable from the input arguments with
some basic arithmetic:

```rust
#[pallet::weight(FunctionOf(
  |args: (&Vec<User>,)| args.0.len().saturating_mul(10_000),
  DispatchClass::Normal,
  Pays::Yes,
))]
fn handle_users(origin, calls: Vec<User>) {
    // Do something per user
}
```

## Post dispatch weight correction

Depending on the execution logic, a dispatchable may consume less weight than was prescribed
pre-dispatch. Why this is useful is explained in the
[weights article](/v3/concepts/weight#post-dispatch-weight-correction). In order to correct
weight, the dispatchable declares a different return type and then returns its actual weight:

```rust
#[pallet::weight(10_000 + 500_000_000)]
fn expensive_or_cheap(input: u64) -> DispatchResultWithPostInfo {
    let was_heavy = do_calculation(input);

    if (was_heavy) {
        // None means "no correction" from the weight annotation.
        Ok(None.into())
    } else {
        // Return the actual weight consumed.
        Ok(Some(10_000).into())
    }
}
```

## Custom fees

You can also define custom fee systems through custom weight functions or inclusion fee functions.

### Custom weights

Instead of using the default weight annotations described above, one can create a custom weight
calculation type. This type must implement the follow traits:

- [`WeighData<T>`]: To determine the weight of the dispatch.
- [`ClassifyDispatch<T>`]: To determine the class of the dispatch.
- [`PaysFee<T>`]: To determine whether the dispatchable's sender pays fees.

Substrate then bundles the output information of the two traits into the [`DispatchInfo`] struct and
provides it by implementing the [`GetDispatchInfo`] for all `Call` variants and opaque extrinsic
types. This is used internally by the System and Executive modules; you probably won't use it.

`ClassifyDispatch`, `WeighData`, and `PaysFee` are generic over `T`, which gets resolved into the
tuple of all dispatch arguments except for the origin. To demonstrate, we will craft a struct that
calculates the weight as `m * len(args)` where `m` is a given multiplier and `args` is the
concatenated tuple of all dispatch arguments. Further, the dispatch class is `Operational` if the
transaction has more than 100 bytes of length in arguments and will pay fees if the encoded length
is greater than 10 bytes.

```rust
struct LenWeight(u32);
impl<T> WeighData<T> for LenWeight {
    fn weigh_data(&self, target: T) -> Weight {
        let multiplier = self.0;
        let encoded_len = target.encode().len() as u32;
        multiplier * encoded_len
    }
}

impl<T> ClassifyDispatch<T> for LenWeight {
    fn classify_dispatch(&self, target: T) -> DispatchClass {
        let encoded_len = target.encode().len() as u32;
        if encoded_len > 100 {
            DispatchClass::Operational
        } else {
            DispatchClass::Normal
        }
    }
}

impl<T> PaysFee<T> {
    fn pays_fee(&self, target: T) -> Pays {
        let encoded_len = target.encode().len() as u32;
        if encoded_len > 10 {
            Pays::Yes
        } else {
            Pays::No
        }
    }
}
```

A weight calculator function can also be coerced to the final type of the argument, instead of
defining it as a vague type that is encodable. `pallet-example` contains an example of how to do
this. Just note that, in that case, your code would roughly look like:

```rust
struct CustomWeight;
impl WeighData<(&u32, &u64)> for CustomWeight {
    fn weigh_data(&self, target: (&u32, &u64)) -> Weight {
        ...
    }
}

// given a dispatch:
#[pallet::call]
impl<T: Config<I>, I: 'static> Pallet<T, I> {
    #[pallet::weight(CustomWeight)]
    fn foo(a: u32, b: u64) { ... }
}
```

This means that `CustomWeight` can only be used in conjunction with a dispatch with a particular
signature `(u32, u64)`, as opposed to `LenWeight`, which can be used with anything because they
don't make any strict assumptions about `<T>`.

### Custom inclusion fee

This is an example of how to customize your inclusion fee. You must configure the appropriate
associated types in the respective module.

```rust
// Assume this is the balance type
type Balance = u64;

// Assume we want all the weights to have a `100 + 2 * w` conversion to fees
struct CustomWeightToFee;
impl Convert<Weight, Balance> for CustomWeightToFee {
    fn convert(w: Weight) -> Balance {
        let a = Balance::from(100);
        let b = Balance::from(2);
        let w = Balance::from(w);
        a + b * w
    }
}

parameter_types! {
    pub const ExtrinsicBaseWeight: Weight = 10_000_000;
}

impl frame_system::Config for Runtime {
    type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
}

parameter_types! {
    pub const TransactionByteFee: Balance = 10;
}

impl transaction_payment::Config {
    type TransactionByteFee = TransactionByteFee;
    type WeightToFee = CustomWeightToFee;
    type FeeMultiplierUpdate = TargetedFeeAdjustment<TargetBlockFullness>;
}

struct TargetedFeeAdjustment<T>(sp_std::marker::PhantomData<T>);
impl<T: Get<Perquintill>> Convert<Fixed128, Fixed128> for TargetedFeeAdjustment<T> {
    fn convert(multiplier: Fixed128) -> Fixed128 {
        // Don't change anything. Put any fee update info here.
        multiplier
    }
}
```

## Next steps

The entire logic of fees is encapsulated in `pallet-transaction-payment` via a [`SignedExtension`](/v3/concepts/tx-pool#signed-extensions).
While this pallet provides a high degree of flexibility, a user can opt to build their custom
payment module drawing inspiration from Transaction Payment.

Given now you know what Substrate's weight system is, how it affects transaction fee computation, and how to specify
them for your dispatchables, the last question is how to find the right weights for your dispatchables.
That is what **Substrate benchmarking** is for. By writing benchmarking functions and running them, the system
(`frame-benchmarking`) calls these functions repeatedly with different numerical parameters and empirically determine
the weight functions for dispatchables in their worst case scenarios, within a certain limit. For more information, see [Benchmarking](/v3/runtime/benchmarking).

- Dedicated [weight documentation](/v3/concepts/weight)
- [Example pallet](https://github.com/paritytech/substrate/tree/master/frame/examples/basic)
- [SignedExtension](/rustdocs/latest/sp_runtime/traits/trait.SignedExtension.html)

### Examples

You can find examples of custom weights and fees in the following repositories:

- [Custom weights for the Example pallet](https://github.com/paritytech/substrate/blob/master/frame/examples/basic/src/weights.rs)
- [Custom WeightToFee how-to guide](/how-to-guides/v3/weights/calculate-fees)

### References

- [Web3 Foundation Research](https://w3f-research.readthedocs.io/en/latest/polkadot/overview/2-token-economics.html#relay-chain-transaction-fees-and-per-block-transaction-limits)
